#ifndef __MATHTOOLS_PLANE_H_INCLUDE__
#define __MATHTOOLS_PLANE_H_INCLUDE__
#include "mathToolsConfig.h"
#include "quaternion.h"
#include "vec3f.h"


namespace mt
{
	class mat4;
	class plane
	{
	public:
		plane();
		plane(const plane& other);
		plane(float _x, float _y, float _z, float _w);
		plane(const vec3f& normal, float d);
		plane(const vec3f& point1, const vec3f& point2, const vec3f& point3);
		plane(const vec3f& point, const vec3f& normal);
		explicit plane(const DirectX::XMFLOAT4& v);
		explicit plane(const float *pArray);
		plane(DirectX::XMVECTOR& V);

		DirectX::XMVECTOR getXMVector() const;

		void store(DirectX::XMVECTOR& v);
		// Comparision operators
		bool operator == (const plane& p) const;
		bool operator != (const plane& p) const;

		// Assignment operators
		plane& operator= (const plane& p);

		// Properties
		vec3f normal() const;
		void Normal(const vec3f& normal);

		float d() const;
		void d(float d);

		// plane operations
		void Normalize();
		void Normalize(plane& result) const;

		float Dot(const DirectX::XMFLOAT4& v) const;

		float DotCoordinate(const vec3f& position) const;

		float DotNormal(const vec3f& normal) const;

		vec3f getMemberPoint()const;

		void setPlane(const vec3f& point, const vec3f& nvector);

		//! Recalculates the distance from origin by applying a new member point to the plane.
		void recalculateD(const vec3f& MPoint);

		// Static functions
		static void Transform(plane& result, const plane& plane0, const DirectX::XMFLOAT4X4& M);

		static void Transform(plane& result, const plane& plane0, const mat4& m);

		static plane Transform(const plane& pl, const DirectX::XMFLOAT4X4& M);

		static void Transform(const plane& plane0, const quaternion& rotation, plane& result);

		static plane Transform(const plane& plane0, const quaternion& rotation);

		union
		{
			float M[4];
			struct 
			{
				vec3f Normal;
				float D;
			}SND;
			DirectX::XMFLOAT4 Data;
		};
	};
}

#endif//! __MATHTOOLS_PLANE_H_INCLUDE__